/*
 * dataset.cpp
 *
 *  Created on: May 2, 2011
 *      Author: tqlong
 */
#include "../common/common.h"
#include "dataset.h"

InMemoryDataset::InMemoryDataset()
{
}

InMemoryDataset::InMemoryDataset(const std::string& fName,
    const std::string& format, bool inMem)
{
	m_fName = fName;
	m_format = format;
	m_inMem = inMem;
	//load(fName, format, inMem);
}

int InMemoryDataset::load( const std::string& fName, const std::string& format,
    bool inMem)
{
	m_fName = fName;
	m_format = format;
	m_inMem = inMem;
	if (inMem)
	{
		m_n = common::loadVVec(fName, m_set, format);
		m_dim = m_set[0].n_elem;
	}
	else
	{
		if (m_format != "raw")
		{
			Log::m_log << "invalid format=" << QString::fromStdString(m_format) << " should be raw" << endl;
			exit(0);
		}
		m_input.open(m_fName.c_str());
		computeEntrySize();
		Log::m_log << "n=" << m_n << " dim=" << m_dim << " offset=" << m_offset << " entrySize=" << m_entrySize << endl;
		m_vec = vec_type(m_dim);
		m_idx = -1;  // no vector loaded
	}
	return m_n;
}

void InMemoryDataset::reload()
{
	load(m_fName, m_format, m_inMem);
}

// we do not use const functions here to provide more flexibility
// when a dataset may comes from a very large file
int InMemoryDataset::n()
{
	return m_n;
}

int InMemoryDataset::n_dim()
{
	return m_dim;
}

const InMemoryDataset::vec_type& InMemoryDataset::get(int i)
{
	if (m_inMem)
		return m_set[i];
	else
	{
		if (m_idx != i)
		{
			Log::m_log << "."; Log::m_log.flush();
			m_idx = i;
			seek(m_idx);
			readEntry();
		}
		return m_vec;
	}
} // get vector

double InMemoryDataset::get(int i, int dim)
{
	return get(i)[dim];
} // get vector element

void InMemoryDataset::computeEntrySize()
{
	m_input.seekg(0, std::ios::beg);
	char type[4] = "000";
	m_input.read(type, 3);
	if (std::string(type) != "raw")
	{
		Log::m_log << "invalid format=" << type << " should be raw" << endl;
		exit(0);
	}
	binary_read(m_input, m_n);
	binary_read(m_input, m_dim);

	m_entrySize = m_dim*sizeof(double);
	m_offset = 3 + sizeof(m_n) + sizeof(m_dim);
}

void InMemoryDataset::seek(int idx)
{
	m_input.seekg(m_offset+m_entrySize*idx, std::ios::beg);
}

void InMemoryDataset::readEntry()
{
	double *dptr = m_vec.memptr();
	m_input.read((char*)dptr, m_dim*sizeof(double));
}

struct RaDecEntry
{
	long long id;
	long long ra, dec;
};

void RaDecDataset::computeEntrySize()
{
	m_dim = 2;
	m_entrySize = sizeof(RaDecEntry);
	m_offset = 0;
	m_input.seekg(0, std::ios::beg);
	std::ios::pos_type pos = m_input.tellg();
	m_input.seekg(0, std::ios::end);
	std::ios::pos_type end_pos = m_input.tellg();
	long long fSize = end_pos - pos;
	m_n = fSize / m_entrySize;
}

void RaDecDataset::readEntry()
{
	double *dptr = m_vec.memptr();
	long long id;
	binary_read(m_input, id);
	m_input.read((char*)dptr, m_dim*sizeof(double));
}

